package com.example.demo.demos.utils;

import com.example.demo.demos.pojo.TreeNode;
import java.lang.reflect.Field;
import java.util.*;
import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @author lyh
 * @date 2025/9/9 15:19
 */
public class Util {

    /**
     * 获取uuid
     *
     * @return String uuid
     */
    public static String getUuid() {
        return UUID.randomUUID().toString().replaceAll("-", "");
    }

    /**
     * 使用 stream流+递归 生成机构树
     * 调用传参格式: Util.generateTree(organTrees, "0", TreeNode::getId, TreeNode::getParentId, TreeNode::setChildren);
     *
     * @param list         原始列表
     * @param rootParentId 根节点父ID
     * @param getId        主键获取函数
     * @param getPid       父ID获取函数
     * @param childFunc    子节点设置函数
     * @param sortField    排序字段
     * @param sortOrder    排序方向
     * @param <T>          实体类型
     * @return 树形结构列表
     */
    public static <T> List<T> generateTree(List<T> list, Object rootParentId, Function<T, Object> getId, Function<T, Object> getPid, BiConsumer<T, List<T>> childFunc, String sortField, String sortOrder) {
        // 处理默认排序方向
        if (sortOrder == null) {
            sortOrder = "asc";
        }

        // 创建父ID到子节点列表的映射，提高查找效率
        Map<Object, List<T>> childMap = list.stream().collect(Collectors.groupingBy(getPid));

        // 准备排序比较器（用于当前层级的排序）
        Comparator<T> comparator = null;
        if (sortField != null && !sortField.trim().isEmpty()) {
            try {
                comparator = createComparator(sortField, sortOrder);
            } catch (Exception e) {
                // 忽略排序错误（如属性不存在）
                comparator = null;
            }
        }

        // 过滤根节点并构建树
        String finalSortOrder = sortOrder;
        Stream<T> rootStream = list.stream()
                .filter(node -> Objects.equals(getPid.apply(node), rootParentId));

        // 对根节点进行排序（新增的排序步骤）
        if (comparator != null) {
            rootStream = rootStream.sorted(comparator);
        }

        return rootStream
                .peek(node -> {
                    Object id = getId.apply(node);
                    // 获取直接子节点
                    List<T> children = childMap.getOrDefault(id, Collections.emptyList())
                            .stream()
                            .peek(child -> {
                                // 递归生成子树（递归调用会自动排序子层级）
                                List<T> childChildren = generateTree(list, getId.apply(child), getId, getPid, childFunc, sortField, finalSortOrder);
                                childFunc.accept(child, childChildren);
                            })
                            .collect(Collectors.toList());

                    // 对直接子节点列表进行排序（原有功能保留）
                    if (sortField != null && !sortField.trim().isEmpty()) {
                        try {
                            Comparator<T> childComparator = createComparator(sortField, finalSortOrder);
                            children.sort(childComparator);
                        } catch (Exception e) {
                            // 忽略排序错误
                        }
                    }
                    childFunc.accept(node, children);
                })
                .collect(Collectors.toList());
    }

    /**
     * 创建基于属性名和排序方向的比较器
     * @param fieldName 属性名
     * @param sortOrder 排序方向："asc"升序，"desc"降序
     * @return 比较器
     * @param <T> 节点类型
     */
    private static <T> Comparator<T> createComparator(String fieldName, String sortOrder) {
        return (o1, o2) -> {
            try {
                // 通过反射获取属性值
                Field field = o1.getClass().getDeclaredField(fieldName);
                field.setAccessible(true);
                Comparable value1 = (Comparable) field.get(o1);
                Comparable value2 = (Comparable) field.get(o2);

                // 处理null值：null视为最小值
                if (value1 == null && value2 == null) return 0;
                if (value1 == null) return -1;
                if (value2 == null) return 1;

                int compare = value1.compareTo(value2);
                // 根据排序方向调整
                if ("desc".equalsIgnoreCase(sortOrder)) {
                    return -compare;
                } else {
                    return compare;
                }
            } catch (Exception e) {
                return 0; // 出错时视为相等，不改变顺序
            }
        };
    }

    /**
     * 构建机构树并计算每个节点的总人数（包含下级），结果存入personNum字段
     *
     * @param nodes 原始节点列表
     * @return 机构树根节点列表
     */
    public static List<TreeNode> generateOrganTreeWithNum(List<TreeNode> nodes, String rootParentId, String sortField, String sortOrder) {
        // 创建ID到节点的映射
        Map<String, TreeNode> nodeMap = nodes.stream()
                .collect(Collectors.toMap(TreeNode::getId, node -> node));
        // 存储根节点
        List<TreeNode> rootNodes = new ArrayList<>();
        // 构建树结构
        for (TreeNode node : nodes) {
            String parentId = node.getParentId();
            if (rootParentId.equals(parentId)) {
                rootNodes.add(node);
            } else {
                TreeNode parent = nodeMap.get(parentId);
                if (parent != null) {
                    parent.getChildren().add(node);
                }
            }
        }

        // 对每个节点的子节点按指定字段和排序方向排序
        sortTreeNodesByField(rootNodes, sortField, sortOrder);

        // 使用迭代方法计算总人数
        calculateTotalNum(nodes);
        return rootNodes;
    }

    /**
     * 迭代计算节点及其下级的累计人数
     *
     * @param nodes 所有节点列表
     */
    private static void calculateTotalNum(List<TreeNode> nodes) {
        // 创建节点ID到父节点的映射
        Map<String, TreeNode> parentMap = new HashMap<>();
        // 创建节点ID到依赖计数的映射
        Map<String, Integer> dependencyCount = new HashMap<>();
        for (TreeNode node : nodes) {
            // 初始化依赖计数（子节点数量）
            dependencyCount.put(node.getId(), node.getChildren().size());
            // 为每个子节点设置父节点映射
            for (TreeNode child : node.getChildren()) {
                parentMap.put(child.getId(), node);
            }
        }

        // 初始化队列（叶子节点）
        Queue<TreeNode> queue = new LinkedList<>();
        for (TreeNode node : nodes) {
            if (node.getChildren().isEmpty()) {
                queue.add(node);
            }
        }

        // 处理队列
        while (!queue.isEmpty()) {
            TreeNode node = queue.poll();
            // 计算当前节点的总人数：自身personNum + 所有子节点的totalNum
            int total = node.getPersonNum(); // 自身人数
            for (TreeNode child : node.getChildren()) {
                total += child.getTotalNum(); // 累加子节点的总人数
            }
            node.setTotalNum(total); // 保存到 totalNum 字段

            // 处理父节点
            TreeNode parent = parentMap.get(node.getId());
            if (parent != null) {
                // 减少父节点的依赖计数
                int count = dependencyCount.get(parent.getId()) - 1;
                dependencyCount.put(parent.getId(), count);
                // 如果父节点没有未处理的子节点，加入队列
                if (count == 0) {
                    queue.add(parent);
                }
            }
        }
    }

    /**
     * 递归对树节点及其子节点按指定字段和排序方向排序
     *
     * @param nodes     当前层节点列表
     * @param sortField 要排序的字段名
     * @param sortOrder 排序方向："asc"升序，"desc"降序，其他值默认升序
     */
    private static void sortTreeNodesByField(List<TreeNode> nodes, String sortField, String sortOrder) {
        if (nodes == null || nodes.isEmpty()) {
            return;
        }

        // 尝试获取比较器
        Comparator<TreeNode> comparator = getComparatorForField(sortField, sortOrder);
        if (comparator == null) {
            return; // 如果找不到对应属性，忽略排序
        }

        // 对当前层节点排序
        nodes.sort(comparator);

        // 递归对每个节点的子节点排序
        for (TreeNode node : nodes) {
            if (node.getChildren() != null && !node.getChildren().isEmpty()) {
                sortTreeNodesByField(node.getChildren(), sortField, sortOrder);
            }
        }
    }

    /**
     * 根据字段名和排序方向获取对应的比较器
     * 需要排序的字段在这里写一个case分支即可
     *
     * @param fieldName 字段名
     * @param sortOrder 排序方向："asc"升序，"desc"降序，其他值默认升序
     * @return 对应的比较器，如果字段不存在返回null
     */
    private static Comparator<TreeNode> getComparatorForField(String fieldName, String sortOrder) {
        Comparator<TreeNode> comparator = null;

        // 根据字段名获取基础比较器
        switch (fieldName) {
            case "sort":
                comparator = Comparator.comparing(TreeNode::getSort,
                        Comparator.nullsFirst(Comparator.naturalOrder()));
                break;
            case "personNum":
                comparator = Comparator.comparing(TreeNode::getPersonNum,
                        Comparator.nullsFirst(Comparator.naturalOrder()));
                break;
            case "name":
                comparator = Comparator.comparing(TreeNode::getName,
                        Comparator.nullsFirst(Comparator.naturalOrder()));
                break;
            case "id":
                comparator = Comparator.comparing(TreeNode::getId,
                        Comparator.nullsFirst(Comparator.naturalOrder()));
                break;
            default:
                // 对于不支持的字段，返回null表示忽略排序
                return null;
        }

        // 根据排序方向调整比较器
        if ("desc".equalsIgnoreCase(sortOrder)) {
            return comparator.reversed();
        } else {
            return comparator;
        }
    }

}
